////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2009 Daniel F. Hanson
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
////////////////////////////////////////////////////////////////////////////////

using System.Diagnostics;
using Microsoft.Xna.Framework.Content;

namespace SilverLua
{
   public class ScriptReader : ContentTypeReader<ScriptBinary>
   {
      protected override ScriptBinary Read(ContentReader input, ScriptBinary existingInstance)
      {
         Debug.Assert(input.ReadChar() == 'S');
         Debug.Assert(input.ReadChar() == 'L');
         Debug.Assert(input.ReadChar() == 'U');
         Debug.Assert(input.ReadChar() == 'A');
         Debug.Assert(input.ReadInt32() == 1);
         Debug.Assert(input.ReadInt32() == 0);

         int chunkCount = input.ReadInt32();
         Chunk[] chunks = new Chunk[chunkCount];
         
         for (int i = 0; i < chunkCount; ++i)
         {
            int registerCount = input.ReadInt32();
            int instrCount = input.ReadInt32();
            Instruction[] instructions = new Instruction[instrCount];
            
            for (int j = 0; j < instrCount; ++j)
            {
               Opcode opcode = (Opcode)input.ReadInt32();
               int operandCount = input.ReadInt32();
               OperandType[] types = new OperandType[operandCount];
               int[] values = new int[operandCount];
               
               for (int k = 0; k < operandCount; ++k)
               {
                  types[k] = (OperandType)input.ReadInt32();
                  values[k] = input.ReadInt32();
               }

               instructions[j] = new Instruction(opcode, types, values);
            }
            
            int upvalueCount = input.ReadInt32();
            Upvalue[] upvalues = new Upvalue[upvalueCount];
            
            for (int j = 0; j < upvalueCount; ++j)
            {
               upvalues[j] = new Upvalue { Type = (OperandType)input.ReadInt32(),
                                           Register = input.ReadInt32() };
            }

            string[] stringTable = new string[input.ReadInt32()];

            for (int j = 0; j < stringTable.Length; ++j)
            {
               stringTable[j] = input.ReadString();
            }

            chunks[i] = new Chunk(instructions, registerCount, upvalues, stringTable);
         }
         
         return new ScriptBinary(chunks);
      }
   }
}
